home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / DXTex / dxtexview.cpp < prev    next >
C/C++ Source or Header  |  2001-10-08  |  30KB  |  1,071 lines

  1. // dxtexView.cpp : implementation of the CDxtexView class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "dxtex.h"
  6. #include "dxtexDoc.h"
  7. #include "dxtexView.h"
  8.  
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14.  
  15. // Our custom vertex type
  16. struct CUSTOMVERTEX
  17. {
  18.     FLOAT x, y, z;
  19.     FLOAT rhw;
  20.     DWORD color;
  21.     FLOAT tu, tv;   // The texture coordinates
  22. };
  23.  
  24. #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)
  25.  
  26.  
  27. IMPLEMENT_DYNCREATE(CDxtexView, CScrollView)
  28.  
  29. BEGIN_MESSAGE_MAP(CDxtexView, CScrollView)
  30.     //{{AFX_MSG_MAP(CDxtexView)
  31.     ON_WM_LBUTTONUP()
  32.     ON_COMMAND(ID_FILE_OPENSUBSURFACE, OnFileOpenSubsurface)
  33.     ON_COMMAND(ID_FILE_OPENALPHASUBSURFACE, OnFileOpenAlphaSubsurface)
  34.     ON_COMMAND(ID_FILE_OPENFACE, OnFileOpenFace)
  35.     ON_COMMAND(ID_FILE_OPENALPHAFACE, OnFileOpenAlphaFace)
  36.     ON_COMMAND(ID_VIEW_ORIGINAL, OnViewOriginal)
  37.     ON_COMMAND(ID_VIEW_COMPRESSED, OnViewCompressed)
  38.     ON_COMMAND(ID_VIEW_SMALLERMIPLEVEL, OnViewSmallerMipLevel)
  39.     ON_COMMAND(ID_VIEW_LARGERMIPLEVEL, OnViewLargerMipLevel)
  40.     ON_COMMAND(ID_VIEW_ALPHACHANNEL, OnViewAlphaChannel)
  41.     ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomIn)
  42.     ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomOut)
  43.     ON_COMMAND(ID_VIEW_CHANGEBACKGROUNDCOLOR, OnViewChangeBackgroundColor)
  44.     ON_COMMAND(ID_VIEW_NEGX, OnViewNegX)
  45.     ON_COMMAND(ID_VIEW_POSX, OnViewPosX)
  46.     ON_COMMAND(ID_VIEW_NEGY, OnViewNegY)
  47.     ON_COMMAND(ID_VIEW_POSY, OnViewPosY)
  48.     ON_COMMAND(ID_VIEW_NEGZ, OnViewNegZ)
  49.     ON_COMMAND(ID_VIEW_POSZ, OnViewPosZ)
  50.     ON_COMMAND(ID_VIEW_HIGHERVOLUMESLICE, OnViewHigherVolumeSlice)
  51.     ON_COMMAND(ID_VIEW_LOWERVOLUMESLICE, OnViewLowerVolumeSlice)
  52.     ON_UPDATE_COMMAND_UI(ID_FILE_OPENSUBSURFACE, OnUpdateFileOpenSubsurface)
  53.     ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHASUBSURFACE, OnUpdateFileOpenAlphaSubsurface)
  54.     ON_UPDATE_COMMAND_UI(ID_FILE_OPENFACE, OnUpdateFileOpenFace)
  55.     ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHAFACE, OnUpdateFileOpenAlphaFace)
  56.     ON_UPDATE_COMMAND_UI(ID_VIEW_ORIGINAL, OnUpdateViewOriginal)
  57.     ON_UPDATE_COMMAND_UI(ID_VIEW_COMPRESSED, OnUpdateViewCompressed)
  58.     ON_UPDATE_COMMAND_UI(ID_VIEW_ALPHACHANNEL, OnUpdateViewAlphaChannel)
  59.     ON_UPDATE_COMMAND_UI(ID_VIEW_LARGERMIPLEVEL, OnUpdateViewLargerMipLevel)
  60.     ON_UPDATE_COMMAND_UI(ID_VIEW_SMALLERMIPLEVEL, OnUpdateViewSmallerMipLevel)
  61.     ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMIN, OnUpdateViewZoomIn)
  62.     ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMOUT, OnUpdateViewZoomOut)
  63.     ON_UPDATE_COMMAND_UI(ID_VIEW_NEGX, OnUpdateViewNegX)
  64.     ON_UPDATE_COMMAND_UI(ID_VIEW_POSX, OnUpdateViewPosX)
  65.     ON_UPDATE_COMMAND_UI(ID_VIEW_NEGY, OnUpdateViewNegY)
  66.     ON_UPDATE_COMMAND_UI(ID_VIEW_POSY, OnUpdateViewPosY)
  67.     ON_UPDATE_COMMAND_UI(ID_VIEW_NEGZ, OnUpdateViewNegZ)
  68.     ON_UPDATE_COMMAND_UI(ID_VIEW_POSZ, OnUpdateViewPosZ)
  69.     ON_UPDATE_COMMAND_UI(ID_VIEW_HIGHERVOLUMESLICE, OnUpdateViewHigherVolumeSlice)
  70.     ON_UPDATE_COMMAND_UI(ID_VIEW_LOWERVOLUMESLICE, OnUpdateViewLowerVolumeSlice)
  71.     //}}AFX_MSG_MAP
  72. END_MESSAGE_MAP()
  73.  
  74.  
  75. CDxtexView::CDxtexView()
  76. {
  77.     m_pVB = NULL;
  78.     m_ptexCur = NULL;
  79.     m_pSwapChain = NULL;
  80.     m_lwMipCur = 0;
  81.     m_CubeFaceCur = D3DCUBEMAP_FACE_FORCE_DWORD;
  82.     m_lwSliceCur = -1;
  83.     m_fZoom = 1.0f;
  84.     m_bViewOrig = TRUE;
  85.     m_bViewAlpha = FALSE;
  86. }
  87.  
  88.  
  89. CDxtexView::~CDxtexView()
  90. {
  91.     ReleasePpo(&m_pVB);
  92.     ReleasePpo(&m_ptexCur);
  93.     ReleasePpo(&m_pSwapChain);
  94. }
  95.  
  96.  
  97. // Note: repaints don't require re-rendering, just recopy from back buffer to view's DC
  98. void CDxtexView::OnDraw(CDC* pDC)
  99. {
  100.     CDxtexDoc* pDoc = GetDocument();
  101.     ASSERT_VALID(pDoc);
  102.  
  103.     HRESULT hr;
  104.     CRect rcSrc;
  105.     CRect rcDest;
  106.  
  107.     rcSrc = m_rcSrc;
  108.     rcDest = m_rcDest;
  109.  
  110.     rcDest.OffsetRect(pDC->GetViewportOrg());
  111.  
  112.     // REVIEW: only update dirty region?
  113.     if (m_pSwapChain != NULL)
  114.         hr = m_pSwapChain->Present(&rcSrc, &rcDest, GetSafeHwnd(), NULL);
  115. }
  116.  
  117.  
  118. #ifdef _DEBUG
  119. void CDxtexView::AssertValid() const
  120. {
  121.     CScrollView::AssertValid();
  122. }
  123.  
  124.  
  125. void CDxtexView::Dump(CDumpContext& dc) const
  126. {
  127.     CScrollView::Dump(dc);
  128. }
  129.  
  130.  
  131. CDxtexDoc* CDxtexView::GetDocument() // non-debug version is inline
  132. {
  133.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDxtexDoc)));
  134.     return (CDxtexDoc*)m_pDocument;
  135. }
  136. #endif //_DEBUG
  137.  
  138.  
  139. void CDxtexView::OnLButtonUp(UINT nFlags, CPoint point)
  140. {
  141.     // Button click means toggle compressed / uncompressed view
  142.     if (m_bViewOrig)
  143.         OnViewCompressed();
  144.     else
  145.         OnViewOriginal();
  146.  
  147.     CScrollView::OnLButtonUp(nFlags, point);
  148. }
  149.  
  150.  
  151. void CDxtexView::OnInitialUpdate()
  152. {
  153. #ifdef _WIN64
  154.     SetClassLongPtr(GetSafeHwnd(), GCLP_HBRBACKGROUND, (LONG_PTR)CreateSolidBrush(RGB(100, 100, 120)));
  155. #else
  156.     SetClassLong(GetSafeHwnd(), GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(100, 100, 120)));
  157. #endif
  158.  
  159.     if (GetDocument()->IsCubeMap())
  160.         m_CubeFaceCur = D3DCUBEMAP_FACE_POSITIVE_X;
  161.     else
  162.         m_CubeFaceCur = D3DCUBEMAP_FACE_FORCE_DWORD;
  163.     if (GetDocument()->IsVolumeMap())
  164.         m_lwSliceCur = 0;
  165.     BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  166.     UpdateDevice();
  167.     CreateVertexBuffer();
  168.     RenderScene();
  169.  
  170.     SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
  171.     ResizeParentToFit();
  172.  
  173.     CScrollView::OnInitialUpdate();
  174.  
  175.     m_bTitleModsChanged = TRUE; // force title bar update
  176. }
  177.  
  178.  
  179. VOID CDxtexView::GetImageInfo(CString& strInfo)
  180. {
  181.     LPDIRECT3DBASETEXTURE8 ptex;
  182.     D3DSURFACE_DESC sd;
  183.     D3DVOLUME_DESC vd;
  184.     D3DFORMAT fmt;
  185.     DWORD dwWidth;
  186.     DWORD dwHeight;
  187.     DWORD dwDepth;
  188.     CString strFormat;
  189.     TCHAR sz[100];
  190.     DWORD dwBytes = 0;
  191.     UINT iLevel;
  192.  
  193.     if (m_bViewOrig)
  194.         ptex = GetDocument()->PtexOrig();
  195.     else
  196.         ptex = GetDocument()->PtexNew();
  197.  
  198.     if (GetDocument()->IsVolumeMap())
  199.     {
  200.         ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(0, &vd);
  201.         fmt = vd.Format;
  202.         dwWidth = vd.Width;
  203.         dwHeight = vd.Height;
  204.         dwDepth = vd.Depth;
  205.     }
  206.     else if (!GetDocument()->IsCubeMap())
  207.     {
  208.         ((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(0, &sd);
  209.         fmt = sd.Format;
  210.         dwWidth = sd.Width;
  211.         dwHeight = sd.Height;
  212.         dwDepth = 0;
  213.     }
  214.     else
  215.     {
  216.         ((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(0, &sd);
  217.         fmt = sd.Format;
  218.         dwWidth = sd.Width;
  219.         dwHeight = sd.Height;
  220.         dwDepth = 0;
  221.     }
  222.  
  223.     strFormat = FormatName(fmt);
  224.  
  225.     // Count bytes in main surface chain
  226.     if (GetDocument()->IsVolumeMap())
  227.     {
  228.         for (iLevel = 0; iLevel < GetDocument()->NumMips(); iLevel++)
  229.         {
  230.             ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(iLevel, &vd);
  231.             dwBytes += vd.Size;
  232.         }
  233.     }
  234.     else if (!GetDocument()->IsCubeMap())
  235.     {
  236.         dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_FORCE_DWORD, ptex);
  237.     }
  238.     else
  239.     {
  240.         dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_X, ptex);
  241.         dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_X, ptex);
  242.         dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_Y, ptex);
  243.         dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_Y, ptex);
  244.         dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_Z, ptex);
  245.         dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_Z, ptex);
  246.     }
  247.  
  248.     if (dwDepth == 0)
  249.         wsprintf(sz, "%d x %d, %s, %d bytes", dwWidth, dwHeight, strFormat, dwBytes);
  250.     else
  251.         wsprintf(sz, "%d x %d x %d, %s, %d bytes", dwWidth, dwHeight, dwDepth, strFormat, dwBytes);
  252.     strInfo = sz;
  253. }
  254.  
  255.  
  256. DWORD CDxtexView::NumBytesInSurfaces(D3DCUBEMAP_FACES FaceType, LPDIRECT3DBASETEXTURE8 ptex)
  257. {
  258.     DWORD dwBytes = 0;
  259.     LPDIRECT3DTEXTURE8 pmiptex = NULL;
  260.     LPDIRECT3DCUBETEXTURE8 pcubetex = NULL;
  261.     D3DSURFACE_DESC sd;
  262.     DWORD iLevel;
  263.  
  264.     if (FaceType == D3DCUBEMAP_FACE_FORCE_DWORD)
  265.         pmiptex = (LPDIRECT3DTEXTURE8)ptex;
  266.     else
  267.         pcubetex = (LPDIRECT3DCUBETEXTURE8)ptex;
  268.  
  269.     for (iLevel = 0; iLevel < GetDocument()->NumMips(); iLevel++)
  270.     {
  271.         if (pmiptex != NULL)
  272.             pmiptex->GetLevelDesc(iLevel, &sd);
  273.         else
  274.             pcubetex->GetLevelDesc(iLevel, &sd);
  275.         dwBytes += sd.Size;
  276.     }
  277.  
  278.     return dwBytes;
  279. }
  280.  
  281.  
  282. HRESULT CDxtexView::UpdateDevice(VOID)
  283. {
  284.     HRESULT hr;
  285.     LPDIRECT3D8 pd3d = PDxtexApp()->Pd3d();
  286.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  287.     D3DDISPLAYMODE dispMode;
  288.     D3DPRESENT_PARAMETERS presentParams;
  289.  
  290.     pd3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispMode);
  291.  
  292.     ReleasePpo(&m_pSwapChain);
  293.     ZeroMemory(&presentParams, sizeof(presentParams));
  294.     presentParams.Windowed = TRUE;
  295.     presentParams.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
  296.     presentParams.BackBufferWidth = m_rcSrc.Width();
  297.     presentParams.BackBufferHeight = m_rcSrc.Height();
  298.     presentParams.BackBufferFormat = dispMode.Format;
  299.  
  300.     if (FAILED(hr = pd3ddev->CreateAdditionalSwapChain(&presentParams, &m_pSwapChain)))
  301.         return hr;
  302.  
  303.     COLORREF crBkgd;
  304.     crBkgd = PDxtexApp()->GetProfileInt("Settings", "Background Color", RGB(0, 255, 255));
  305.     m_dwClearColor = D3DCOLOR_RGBA(GetRValue(crBkgd), GetGValue(crBkgd), GetBValue(crBkgd), 255);
  306.  
  307.     return S_OK;
  308. }
  309.  
  310.  
  311. HRESULT CDxtexView::CreateVertexBuffer(VOID)
  312. {
  313.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  314.  
  315.     // Create the the vertex buffer
  316.     if( FAILED( pd3ddev->CreateVertexBuffer( 6 * sizeof(CUSTOMVERTEX),
  317.         0 /* Usage */, D3DFVF_CUSTOMVERTEX, 
  318.         D3DPOOL_DEFAULT, &m_pVB ) ) )
  319.     {
  320.         return E_FAIL;
  321.     }
  322.  
  323.     return S_OK;
  324. }
  325.  
  326.  
  327. HRESULT CDxtexView::RenderScene(VOID)
  328. {
  329.     CWaitCursor waitCursor;
  330.     HRESULT hr;
  331.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  332.  
  333.     LPDIRECT3DSURFACE8 psurf;
  334.  
  335.     if (m_pSwapChain == NULL)
  336.         return E_FAIL;
  337.  
  338.     // Vertices for our quad
  339.     CUSTOMVERTEX vertexArray[] =
  340.     {
  341.         // x, y, z, rhw, color
  342.         { 0.0f,                                 0.0f,                              0.5f, 1.0f, 0xffffffff, 0.0, 0.0, },
  343.         { (FLOAT)m_rcSrc.right, 0.0f,                              0.5f, 1.0f, 0xffffffff, 1.0, 0.0, },
  344.         { (FLOAT)m_rcSrc.right, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 1.0, 1.0, },
  345.  
  346.         { (FLOAT)m_rcSrc.right, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 1.0, 1.0, },
  347.         { 0.0f,                                 (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 0.0, 1.0, },
  348.         { 0.0f,                                 0.0f,                              0.5f, 1.0f, 0xffffffff, 0.0, 0.0, },
  349.     };
  350.  
  351.     // Copy the global vertex data into the vertex buffer
  352.     VOID* pVertices;
  353.     if( FAILED( m_pVB->Lock( 0, sizeof(vertexArray), (BYTE**)&pVertices, 0 ) ) )
  354.         return E_FAIL;
  355.     memcpy( pVertices, vertexArray, sizeof(vertexArray) );
  356.     m_pVB->Unlock();
  357.  
  358.     hr = m_pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &psurf);
  359.  
  360.     hr = pd3ddev->SetRenderTarget(psurf, NULL);
  361.  
  362.     ReleasePpo(&psurf);
  363.  
  364.     hr = pd3ddev->Clear(0, NULL, D3DCLEAR_TARGET, m_dwClearColor, 0.0f, 0);
  365.  
  366.     hr = pd3ddev->BeginScene();
  367.  
  368.     // If the texture uses premultiplied alpha, the source blend should be D3DBLEND_ONE
  369.     // since RGB is already at the level we want.  With nonpremultiplied alpha, the
  370.     // source blend should be D3DBLEND_SRCALPHA.
  371.     D3DSURFACE_DESC sd;
  372.     m_ptexCur->GetLevelDesc(0, &sd);
  373.     if (!m_bViewAlpha && (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4))
  374.     {
  375.         if (FAILED(hr = pd3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE)))
  376.             return hr;
  377.     }
  378.     else
  379.     {
  380.         if (FAILED(hr = pd3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)))
  381.             return hr;
  382.     }
  383.     hr = pd3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  384.     hr = pd3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  385.  
  386.     pd3ddev->SetTexture(0, m_ptexCur);
  387.     pd3ddev->SetStreamSource( 0, m_pVB, sizeof(CUSTOMVERTEX) );
  388.     pd3ddev->SetVertexShader( D3DFVF_CUSTOMVERTEX );
  389.     pd3ddev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
  390.     pd3ddev->SetTexture(0, NULL);
  391.  
  392.     hr = pd3ddev->EndScene();
  393.  
  394.     return S_OK;
  395. }
  396.  
  397.  
  398. void CDxtexView::OnViewOriginal()
  399. {
  400.     if (GetDocument()->PtexOrig() == NULL)
  401.         return;
  402.     BuildViewSurface(TRUE, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  403.     RenderScene();
  404.     m_bTitleModsChanged = TRUE; // force title bar update
  405.     InvalidateRect(&m_rcDest, FALSE); // force redraw of this view
  406. }
  407.  
  408.  
  409. void CDxtexView::OnViewCompressed()
  410. {
  411.     if (GetDocument()->PtexNew() == NULL)
  412.         return;
  413.     BuildViewSurface(FALSE, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  414.     RenderScene();
  415.     m_bTitleModsChanged = TRUE; // force title bar update
  416.     InvalidateRect(&m_rcDest, FALSE); // force redraw of this view
  417. }
  418.  
  419.  
  420. void CDxtexView::OnUpdateViewOriginal(CCmdUI* pCmdUI)
  421. {
  422.     if (GetDocument()->PtexOrig() == NULL)
  423.     {
  424.         pCmdUI->Enable(FALSE);
  425.         pCmdUI->SetCheck(0);
  426.     }
  427.     else
  428.     {
  429.         pCmdUI->Enable(TRUE);
  430.         pCmdUI->SetCheck(m_bViewOrig);
  431.     }
  432. }
  433.  
  434.  
  435. void CDxtexView::OnUpdateViewCompressed(CCmdUI* pCmdUI)
  436. {
  437.     if (GetDocument()->PtexNew() == NULL)
  438.     {
  439.         pCmdUI->Enable(FALSE);
  440.         pCmdUI->SetCheck(0);
  441.     }
  442.     else
  443.     {
  444.         pCmdUI->Enable(TRUE);
  445.         pCmdUI->SetCheck(!m_bViewOrig);
  446.     }
  447. }
  448.  
  449.  
  450. void CDxtexView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
  451. {
  452.     m_bTitleModsChanged = TRUE; // force title bar update
  453.     if (lHint == 1)
  454.     {
  455.         BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  456.         RenderScene();
  457.     }
  458.     else if (lHint == 2)
  459.     {
  460.         UpdateDevice();
  461.         RenderScene();
  462.     }
  463.     else if (lHint == 3)
  464.     {
  465.         RenderScene();
  466.     }
  467.  
  468.     CScrollView::OnUpdate(pSender, lHint, pHint);
  469. }
  470.  
  471.  
  472. void CDxtexView::OnViewSmallerMipLevel()
  473. {
  474.     m_lwMipCur++;
  475.     if (m_lwSliceCur > 0)
  476.         m_lwSliceCur /= 2;
  477.     BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  478.     UpdateDevice();
  479.     RenderScene();
  480.     m_bTitleModsChanged = TRUE; // force title bar update
  481.     SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
  482.     Invalidate(); // force redraw of this view
  483. }
  484.  
  485.  
  486. void CDxtexView::OnViewLargerMipLevel()
  487. {
  488.     m_lwMipCur--;
  489.     if (m_lwSliceCur > 0)
  490.         m_lwSliceCur *= 2;
  491.     BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  492.     UpdateDevice();
  493.     RenderScene();
  494.     m_bTitleModsChanged = TRUE; // force title bar update
  495.     SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
  496.     Invalidate(); // force redraw of this view
  497. }
  498.  
  499.  
  500. void CDxtexView::OnViewAlphaChannel(VOID)
  501. {
  502.     BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, !m_bViewAlpha);
  503.     RenderScene();
  504.     Invalidate(); // force redraw of this view
  505.     m_bTitleModsChanged = TRUE; // force title bar update
  506. }
  507.  
  508.  
  509. void CDxtexView::OnUpdateViewAlphaChannel(CCmdUI* pCmdUI)
  510. {
  511.     pCmdUI->SetCheck(m_bViewAlpha);
  512. }
  513.  
  514.  
  515. void CDxtexView::OnUpdateViewLargerMipLevel(CCmdUI* pCmdUI)
  516. {
  517.     if (m_lwMipCur > 0)
  518.         pCmdUI->Enable(TRUE);
  519.     else
  520.         pCmdUI->Enable(FALSE);
  521. }
  522.  
  523.  
  524. void CDxtexView::OnUpdateViewSmallerMipLevel(CCmdUI* pCmdUI)
  525. {
  526.     if (m_lwMipCur < (LONG)GetDocument()->NumMips() - 1)
  527.         pCmdUI->Enable(TRUE);
  528.     else
  529.         pCmdUI->Enable(FALSE);
  530. }
  531.  
  532.  
  533. void CDxtexView::OnViewZoomIn()
  534. {
  535.     if (m_fZoom < 8.0f)
  536.         m_fZoom *= 2.0f;
  537.     m_rcDest.right = (LONG)(m_rcSrc.right * m_fZoom);
  538.     m_rcDest.bottom = (LONG)(m_rcSrc.bottom * m_fZoom);
  539.     SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
  540.     m_bTitleModsChanged = TRUE; // force title bar update
  541.     Invalidate(); // force redraw of this view
  542. }
  543.  
  544.  
  545. void CDxtexView::OnViewZoomOut()
  546. {
  547.     if (m_fZoom > 0.125f)
  548.         m_fZoom /= 2.0f;
  549.     m_rcDest.right = (LONG)(m_rcSrc.right * m_fZoom);
  550.     m_rcDest.bottom = (LONG)(m_rcSrc.bottom * m_fZoom);
  551.     SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
  552.     m_bTitleModsChanged = TRUE; // force title bar update
  553.     Invalidate(); // force redraw of this view
  554. }
  555.  
  556.  
  557. void CDxtexView::OnUpdateViewZoomIn(CCmdUI* pCmdUI)
  558. {
  559.     pCmdUI->Enable(m_fZoom < 8.0f);
  560. }
  561.  
  562.  
  563. void CDxtexView::OnUpdateViewZoomOut(CCmdUI* pCmdUI)
  564. {
  565.     pCmdUI->Enable(m_fZoom > 0.125f);
  566. }
  567.  
  568.  
  569. CString CDxtexView::GetStrTitleMods(VOID)
  570. {
  571.     CString strTitleMods;
  572.     strTitleMods = "(";
  573.  
  574.     // Append alpha, if in alpha mode
  575.     if (m_bViewAlpha)
  576.             strTitleMods += "Alpha, ";
  577.  
  578.     // Show format
  579.     LPDIRECT3DBASETEXTURE8 ptex;
  580.     CString strFormat;
  581.     D3DFORMAT fmt;
  582.  
  583.     if (m_bViewOrig)
  584.         ptex = GetDocument()->PtexOrig();
  585.     else
  586.         ptex = GetDocument()->PtexNew();
  587.  
  588.     if (GetDocument()->IsVolumeMap())
  589.     {
  590.         D3DVOLUME_DESC vd;
  591.         ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(0, &vd);
  592.         fmt = vd.Format;
  593.     }
  594.     else if (!GetDocument()->IsCubeMap())
  595.     {
  596.         D3DSURFACE_DESC sd;
  597.         ((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(0, &sd);
  598.         fmt = sd.Format;
  599.     }
  600.     else
  601.     {
  602.         D3DSURFACE_DESC sd;
  603.         ((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(0, &sd);
  604.         fmt = sd.Format;
  605.     }
  606.  
  607.     strTitleMods += FormatName(fmt);
  608.     strTitleMods += TEXT(", ");
  609.  
  610.     // Append cube map info, if a cube map
  611.     switch (m_CubeFaceCur)
  612.     {
  613.     case D3DCUBEMAP_FACE_NEGATIVE_X:
  614.         strTitleMods += "Negative X, ";
  615.         break;
  616.     case D3DCUBEMAP_FACE_POSITIVE_X:
  617.         strTitleMods += "Positive X, ";
  618.         break;
  619.     case D3DCUBEMAP_FACE_NEGATIVE_Y:
  620.         strTitleMods += "Negative Y, ";
  621.         break;
  622.     case D3DCUBEMAP_FACE_POSITIVE_Y:
  623.         strTitleMods += "Positive Y, ";
  624.         break;
  625.     case D3DCUBEMAP_FACE_NEGATIVE_Z:
  626.         strTitleMods += "Negative Z, ";
  627.         break;
  628.     case D3DCUBEMAP_FACE_POSITIVE_Z:
  629.         strTitleMods += "Positive Z, ";
  630.         break;
  631.     }
  632.  
  633.     if (m_lwSliceCur >= 0)
  634.     {
  635.         CString strSlice;
  636.         strSlice.Format("Slice %d of %d, ", m_lwSliceCur + 1, GetDocument()->DwDepthAt(m_lwMipCur));
  637.         strTitleMods += strSlice;
  638.     }
  639.  
  640.     // Append mip info, if multiple mip levels
  641.     DWORD dwNumMips = GetDocument()->NumMips();
  642.     if (dwNumMips > 1)
  643.     {
  644.         CString strMipInfo;
  645.         strMipInfo.Format("Mip %d of %d, ", m_lwMipCur + 1, dwNumMips);
  646.         strTitleMods += strMipInfo;
  647.     }
  648.  
  649.     // Append view magnification
  650.     CString strView;
  651.     strView.Format("%d", (LONG)(100 * m_fZoom));
  652.     strTitleMods += strView + "%";
  653.  
  654.     strTitleMods += ")";
  655.     return strTitleMods;
  656. }
  657.  
  658.  
  659. CString CDxtexView::FormatName(D3DFORMAT fmt)
  660. {
  661.     CString str;
  662.     switch (fmt)
  663.     {
  664.     case D3DFMT_A8R8G8B8:
  665.         str = TEXT("A8R8G8B8");
  666.         break;
  667.     case D3DFMT_A1R5G5B5:
  668.         str = TEXT("A1R5G5B5");
  669.         break;
  670.     case D3DFMT_A4R4G4B4:
  671.         str = TEXT("A4R4G4B4");
  672.         break;
  673.     case D3DFMT_R8G8B8:
  674.         str = TEXT("R8G8B8");
  675.         break;
  676.     case D3DFMT_R5G6B5:
  677.         str = TEXT("R5G6B5");
  678.         break;
  679.     case D3DFMT_X8R8G8B8:
  680.         str = TEXT("X8R8G8B8");
  681.         break;
  682.     case D3DFMT_X1R5G5B5:
  683.         str = TEXT("X1R5G5B5");
  684.         break;
  685.     case D3DFMT_R3G3B2:
  686.         str = TEXT("R3G3B2");
  687.         break;
  688.     case D3DFMT_A8R3G3B2:
  689.         str = TEXT("A8R3G3B2");
  690.         break;
  691.     case D3DFMT_X4R4G4B4:
  692.         str = TEXT("X4R4G4B4");
  693.         break;
  694.     case D3DFMT_DXT1:
  695.         str = TEXT("DXT1");
  696.         break;
  697.     case D3DFMT_DXT2:
  698.         str = TEXT("DXT2");
  699.         break;
  700.     case D3DFMT_DXT3:
  701.         str = TEXT("DXT3");
  702.         break;
  703.     case D3DFMT_DXT4:
  704.         str = TEXT("DXT4");
  705.         break;
  706.     case D3DFMT_DXT5:
  707.         str = TEXT("DXT5");
  708.         break;
  709.     default:
  710.         str = TEXT("unknown fmt");
  711.         break;
  712.     }
  713.     return str;
  714. }
  715.  
  716. void CDxtexView::OnViewChangeBackgroundColor()
  717. {
  718.     CHOOSECOLOR cc;
  719.     COLORREF crArray[16];
  720.  
  721.     ZeroMemory(&cc, sizeof(cc));
  722.     cc.lStructSize = sizeof(cc);
  723.     cc.hwndOwner = GetSafeHwnd();
  724.     cc.rgbResult = PDxtexApp()->GetProfileInt("Settings", "Background Color", RGB(0, 255, 255));
  725.     cc.lpCustColors = crArray;
  726.     cc.Flags = CC_RGBINIT | CC_ANYCOLOR | CC_FULLOPEN;
  727.  
  728.     if (ChooseColor(&cc))
  729.     {
  730.         PDxtexApp()->WriteProfileInt("Settings", "Background Color", cc.rgbResult);
  731.  
  732.         // Update all views of all documents of our one doc template
  733.         POSITION posTemp = PDxtexApp()->GetFirstDocTemplatePosition();
  734.         CDocTemplate* pDocTemplate = PDxtexApp()->GetNextDocTemplate(posTemp);
  735.         CDocument* pdoc;
  736.         POSITION pos = pDocTemplate->GetFirstDocPosition();
  737.         while (pos != NULL)
  738.         {
  739.             pdoc = pDocTemplate->GetNextDoc(pos);
  740.             pdoc->UpdateAllViews(NULL, 2);
  741.         }
  742.     }
  743. }
  744.  
  745.  
  746. void CDxtexView::OnFileOpenSubsurface()
  747. {
  748.     GetDocument()->OpenSubsurface(m_CubeFaceCur, m_lwMipCur, m_lwSliceCur);
  749. }
  750.  
  751.  
  752. void CDxtexView::OnUpdateFileOpenSubsurface(CCmdUI* pCmdUI)
  753. {
  754.     pCmdUI->Enable(TRUE);
  755. }
  756.  
  757.  
  758. void CDxtexView::OnFileOpenAlphaSubsurface()
  759. {
  760.     GetDocument()->OpenAlphaSubsurface(m_CubeFaceCur, m_lwMipCur, m_lwSliceCur);
  761. }
  762.  
  763.  
  764. void CDxtexView::OnUpdateFileOpenAlphaSubsurface(CCmdUI* pCmdUI)
  765. {
  766.     pCmdUI->Enable(TRUE);
  767. }
  768.  
  769.  
  770. HRESULT CDxtexView::BuildViewSurface(BOOL bOrig, D3DCUBEMAP_FACES FaceType, LONG lwSlice, LONG lwMip, BOOL bViewAlpha)
  771. {
  772.     HRESULT hr;
  773.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  774.     LPDIRECT3DBASETEXTURE8 ptex;
  775.     BOOL bIsCubeMap = GetDocument()->IsCubeMap();
  776.     BOOL bIsVolumeMap = GetDocument()->IsVolumeMap();
  777.     D3DSURFACE_DESC sd;
  778.     D3DVOLUME_DESC vd;
  779.  
  780.     ReleasePpo(&m_ptexCur);
  781.  
  782.     if (bIsVolumeMap && lwSlice == -1)
  783.         lwSlice = 0;
  784.  
  785.     if (bIsCubeMap && FaceType == D3DCUBEMAP_FACE_FORCE_DWORD)
  786.         FaceType = D3DCUBEMAP_FACE_POSITIVE_X;
  787.  
  788.     m_bViewOrig = bOrig;
  789.     m_bViewAlpha = bViewAlpha;
  790.     m_lwSliceCur = lwSlice;
  791.     m_lwMipCur = lwMip;
  792.     m_CubeFaceCur = FaceType;
  793.  
  794.     if (bOrig)
  795.         ptex = GetDocument()->PtexOrig();
  796.     else
  797.         ptex = GetDocument()->PtexNew();
  798.  
  799.     if (bIsVolumeMap)
  800.     {
  801.         ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(m_lwMipCur, &vd);
  802.         sd.Width = vd.Width;
  803.         sd.Height = vd.Height;
  804.     }
  805.     else if (!bIsCubeMap)
  806.     {
  807.         ((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(m_lwMipCur, &sd);
  808.     }
  809.     else
  810.     {
  811.         ((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(m_lwMipCur, &sd);
  812.     }
  813.  
  814.     hr = pd3ddev->CreateTexture(sd.Width, sd.Height, 1,
  815.          0 /* Usage */, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_ptexCur);
  816.     if (FAILED(hr))
  817.         return hr;
  818.  
  819.     m_rcSrc.SetRect(0, 0, sd.Width, sd.Height);
  820.     m_rcDest.SetRect(0, 0, (INT)(sd.Width * m_fZoom), (INT)(sd.Height * m_fZoom));
  821.  
  822.     LPDIRECT3DSURFACE8 psurfSrc = NULL;
  823.     LPDIRECT3DSURFACE8 psurfDest = NULL;
  824.  
  825.     hr = m_ptexCur->GetSurfaceLevel(0, &psurfDest);
  826.  
  827.     if (bIsVolumeMap)
  828.     {
  829.         LPDIRECT3DVOLUME8 pvolSrc;
  830.         hr = ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetVolumeLevel(m_lwMipCur, &pvolSrc);
  831.         hr = LoadSurfaceFromVolumeSlice(pvolSrc, m_lwSliceCur, psurfDest);
  832.         ReleasePpo(&pvolSrc);
  833.     }
  834.     else if (!bIsCubeMap)
  835.     {
  836.         hr = ((LPDIRECT3DTEXTURE8)ptex)->GetSurfaceLevel(m_lwMipCur, &psurfSrc);
  837.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
  838.             D3DX_FILTER_TRIANGLE, 0);
  839.     }
  840.     else
  841.     {
  842.         hr = ((LPDIRECT3DCUBETEXTURE8)ptex)->GetCubeMapSurface(FaceType, m_lwMipCur, &psurfSrc);
  843.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
  844.             D3DX_FILTER_TRIANGLE, 0);
  845.     }
  846.  
  847.  
  848.     if (bViewAlpha)
  849.     {
  850.         // Move alpha channels into RGB (and set alpha to 0xff)
  851.         D3DLOCKED_RECT lr;
  852.  
  853.         hr = psurfDest->LockRect(&lr, NULL, 0);
  854.  
  855.         DWORD xp;
  856.         DWORD yp;
  857.         DWORD* pdwRow = (DWORD*)lr.pBits;
  858.         DWORD* pdw;
  859.         DWORD dwAlpha;
  860.         LONG dataBytesPerRow = 4 * sd.Width;
  861.  
  862.         for (yp = 0; yp < sd.Height; yp++)
  863.         {
  864.             pdw = pdwRow;
  865.             for (xp = 0; xp < sd.Width; xp++)
  866.             {
  867.                 dwAlpha = *pdw >> 24;
  868.                 *pdw = 0xff000000 | (dwAlpha << 16) | (dwAlpha << 8) | (dwAlpha);
  869.                 pdw++;
  870.             }
  871.             pdwRow += lr.Pitch / 4;
  872.         }
  873.         psurfDest->UnlockRect();
  874.     }
  875.  
  876.     ReleasePpo(&psurfSrc);
  877.     ReleasePpo(&psurfDest);
  878.  
  879.     return S_OK;
  880. }
  881.  
  882.  
  883. HRESULT CDxtexView::LoadSurfaceFromVolumeSlice(LPDIRECT3DVOLUME8 pVolume, UINT iSlice, LPDIRECT3DSURFACE8 psurf)
  884. {
  885.     HRESULT hr;
  886.     D3DVOLUME_DESC vd;
  887.     D3DLOCKED_BOX lb;
  888.     D3DBOX box;
  889.     RECT rc;
  890.  
  891.     pVolume->GetDesc(&vd);
  892.  
  893.     box.Left = 0;
  894.     box.Right = vd.Width;
  895.     box.Top = 0;
  896.     box.Bottom = vd.Height;
  897.     box.Front = iSlice;
  898.     box.Back = iSlice + 1;
  899.  
  900.     rc.left = 0;
  901.     rc.right = vd.Width;
  902.     rc.top = 0;
  903.     rc.bottom = vd.Height;
  904.  
  905.     hr = pVolume->LockBox(&lb, &box, 0);
  906.     if (FAILED(hr))
  907.         return hr;
  908.  
  909.     hr = D3DXLoadSurfaceFromMemory(psurf, NULL, NULL, lb.pBits, vd.Format, lb.RowPitch,
  910.         NULL, &rc, D3DX_FILTER_TRIANGLE, 0);
  911.  
  912.     pVolume->UnlockBox();
  913.  
  914.     return hr;
  915. }
  916.  
  917.  
  918. void CDxtexView::OnViewNegX()
  919. {
  920.     BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_X, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  921.     m_bTitleModsChanged = TRUE; // force title bar update
  922.     RenderScene();
  923.     Invalidate(); // force redraw of this view
  924. }
  925.  
  926.  
  927. void CDxtexView::OnUpdateViewNegX(CCmdUI* pCmdUI)
  928. {
  929.     BOOL bEnable = GetDocument()->IsCubeMap();
  930.     pCmdUI->Enable(bEnable);
  931.     pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_X);
  932. }
  933.  
  934.  
  935. void CDxtexView::OnViewPosX()
  936. {
  937.     BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_X, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  938.     m_bTitleModsChanged = TRUE; // force title bar update
  939.     RenderScene();
  940.     Invalidate(); // force redraw of this view
  941. }
  942.  
  943.  
  944. void CDxtexView::OnUpdateViewPosX(CCmdUI* pCmdUI)
  945. {
  946.     BOOL bEnable = GetDocument()->IsCubeMap();
  947.     pCmdUI->Enable(bEnable);
  948.     pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_X);
  949. }
  950.  
  951.  
  952. void CDxtexView::OnViewNegY()
  953. {
  954.     BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_Y, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  955.     m_bTitleModsChanged = TRUE; // force title bar update
  956.     RenderScene();
  957.     Invalidate(); // force redraw of this view
  958. }
  959.  
  960.  
  961. void CDxtexView::OnUpdateViewNegY(CCmdUI* pCmdUI)
  962. {
  963.     BOOL bEnable = GetDocument()->IsCubeMap();
  964.     pCmdUI->Enable(bEnable);
  965.     pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_Y);
  966. }
  967.  
  968.  
  969. void CDxtexView::OnViewPosY()
  970. {
  971.     BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_Y, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  972.     m_bTitleModsChanged = TRUE; // force title bar update
  973.     RenderScene();
  974.     Invalidate(); // force redraw of this view
  975. }
  976.  
  977.  
  978. void CDxtexView::OnUpdateViewPosY(CCmdUI* pCmdUI)
  979. {
  980.     BOOL bEnable = GetDocument()->IsCubeMap();
  981.     pCmdUI->Enable(bEnable);
  982.     pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_Y);
  983. }
  984.  
  985.  
  986. void CDxtexView::OnViewNegZ()
  987. {
  988.     BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_Z, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  989.     m_bTitleModsChanged = TRUE; // force title bar update
  990.     RenderScene();
  991.     Invalidate(); // force redraw of this view
  992. }
  993.  
  994.  
  995. void CDxtexView::OnUpdateViewNegZ(CCmdUI* pCmdUI)
  996. {
  997.     BOOL bEnable = GetDocument()->IsCubeMap();
  998.     pCmdUI->Enable(bEnable);
  999.     pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_Z);
  1000. }
  1001.  
  1002.  
  1003. void CDxtexView::OnViewPosZ()
  1004. {
  1005.     BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_Z, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  1006.     m_bTitleModsChanged = TRUE; // force title bar update
  1007.     RenderScene();
  1008.     Invalidate(); // force redraw of this view
  1009. }
  1010.  
  1011.  
  1012. void CDxtexView::OnUpdateViewPosZ(CCmdUI* pCmdUI)
  1013. {
  1014.     BOOL bEnable = GetDocument()->IsCubeMap();
  1015.     pCmdUI->Enable(bEnable);
  1016.     pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_Z);
  1017. }
  1018.  
  1019. void CDxtexView::OnFileOpenFace()
  1020. {
  1021.     GetDocument()->OpenCubeFace(m_CubeFaceCur);
  1022. }
  1023.  
  1024. void CDxtexView::OnUpdateFileOpenFace(CCmdUI* pCmdUI)
  1025. {
  1026.     BOOL bEnable = (m_CubeFaceCur != D3DCUBEMAP_FACE_FORCE_DWORD);
  1027.     pCmdUI->Enable(bEnable);
  1028. }
  1029.  
  1030. void CDxtexView::OnFileOpenAlphaFace()
  1031. {
  1032.     GetDocument()->OpenAlphaCubeFace(m_CubeFaceCur);
  1033. }
  1034.  
  1035. void CDxtexView::OnUpdateFileOpenAlphaFace(CCmdUI* pCmdUI)
  1036. {
  1037.     BOOL bEnable = (m_CubeFaceCur != D3DCUBEMAP_FACE_FORCE_DWORD);
  1038.     pCmdUI->Enable(bEnable);
  1039. }
  1040.  
  1041. void CDxtexView::OnViewHigherVolumeSlice()
  1042. {
  1043.     m_lwSliceCur++;
  1044.     BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  1045.     UpdateDevice();
  1046.     RenderScene();
  1047.     m_bTitleModsChanged = TRUE; // force title bar update
  1048.     Invalidate(); // force redraw of this view
  1049. }
  1050.  
  1051. void CDxtexView::OnUpdateViewHigherVolumeSlice(CCmdUI* pCmdUI)
  1052. {
  1053.     pCmdUI->Enable(GetDocument()->IsVolumeMap() && m_lwSliceCur < (LONG)GetDocument()->DwDepthAt(m_lwMipCur) - 1);
  1054. }
  1055.  
  1056. void CDxtexView::OnViewLowerVolumeSlice()
  1057. {
  1058.     m_lwSliceCur--;
  1059.     BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
  1060.     UpdateDevice();
  1061.     RenderScene();
  1062.     m_bTitleModsChanged = TRUE; // force title bar update
  1063.     Invalidate(); // force redraw of this view
  1064. }
  1065.  
  1066. void CDxtexView::OnUpdateViewLowerVolumeSlice(CCmdUI* pCmdUI)
  1067. {
  1068.     pCmdUI->Enable(GetDocument()->IsVolumeMap() && m_lwSliceCur > 0);
  1069. }
  1070.  
  1071.